#include "face_detect_view.hpp"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QFileDialog>
#include <QGroupBox>
#include <QMessageBox>
#include <QCoreApplication>
#include <iostream>

#pragma execution_character_set("utf-8")

FaceDetectView::FaceDetectView()
{
  std::cout << "create MyCustomPanel instance..." << std::endl;
  initUIs();
}

void FaceDetectView::initUIs()
{
  QPixmap pixmap(QDir::homePath() + "/opencv_tutorial_data/images/llk_tpl.png");
  this->image_label = new QLabel();
  image_label->setAlignment(Qt::AlignCenter);
  image_label->setStyleSheet("background-color:rgb(0, 0, 0);color:red");
  image_label->setPixmap(pixmap);
  image_label->setFixedSize(800, 550);
  this->data_file_edit = new QLineEdit();
  this->data_file_edit->setEnabled(false);
  QPushButton *selectBtn = new QPushButton("选择图像");

  img_file_rbt = new QRadioButton("图像文件");
  video_file_rbt = new QRadioButton("视频文件");
  vision_file_rbt = new QRadioButton("摄像头");
  img_file_rbt->setChecked(true);
  QHBoxLayout *box1 = new QHBoxLayout();
  QWidget *panel1 = new QGroupBox("数据");
  box1->addWidget(img_file_rbt);
  box1->addWidget(video_file_rbt);
  box1->addWidget(this->data_file_edit);
  box1->addWidget(selectBtn);
  panel1->setLayout(box1);

  weight_file_edit = new QLineEdit();
  config_file_edit = new QLineEdit();
  weight_file_edit->setEnabled(false);
  config_file_edit->setEnabled(false);
  auto *weight_btn = new QPushButton("选择...");
  auto *config_btn = new QPushButton("选择...");
  QHBoxLayout *box2 = new QHBoxLayout();
  QWidget *panel2 = new QGroupBox("模型");
  box2->addWidget(new QLabel("权重文件"));
  box2->addWidget(weight_file_edit);
  box2->addWidget(weight_btn);
  box2->addWidget(new QLabel("配置文件"));
  box2->addWidget(config_file_edit);
  box2->addWidget(config_btn);
  panel2->setLayout(box2);

  show_fps_chk = new QCheckBox("FPS");
  show_score_chk = new QCheckBox("置信度");
  show_fps_chk->setChecked(true);
  show_score_chk->setChecked(true);
  score_spinbox = new QDoubleSpinBox();
  score_spinbox->setRange(0, 1);
  score_spinbox->setSingleStep(0.01);
  score_spinbox->setValue(0.5);
  QHBoxLayout *box3 = new QHBoxLayout();
  QWidget *panel3 = new QGroupBox("显示");
  box3->addWidget(show_fps_chk);
  box3->addWidget(show_score_chk);
  box3->addWidget(new QLabel("得分: "));
  box3->addWidget(score_spinbox);
  panel3->setLayout(box3);

  QHBoxLayout *hbox4 = new QHBoxLayout();
  QWidget *panel4 = new QWidget();
  this->applyBtn = new QPushButton("运行");
  hbox4->addStretch(1);
  hbox4->addWidget(this->applyBtn);
  panel4->setLayout(hbox4);

  QVBoxLayout *vbox = new QVBoxLayout();
  vbox->addWidget(panel1);
  vbox->addWidget(panel2);
  vbox->addWidget(panel3);
  vbox->addWidget(panel4);
  vbox->addWidget(image_label);
  vbox->addStretch(1);
  this->setLayout(vbox);

  // add listener
  connect(selectBtn, SIGNAL(clicked()), this, SLOT(select_image()));
  connect(weight_btn, SIGNAL(clicked()), this, SLOT(select_weight_file()));
  connect(config_btn, SIGNAL(clicked()), this, SLOT(select_config_file()));
  connect(this->applyBtn, SIGNAL(clicked()), this, SLOT(do_face_detect()));

  InterfaceSettings settings;
  settings.Load_settings();

  std::cout << "weight_file: " << settings.Get_weight_file() << std::endl;
  std::cout << "config_file: " << settings.Get_config_file() << std::endl;
  std::cout << "t_score: " << settings.Get_t_score() << std::endl;
  std::cout << "show_fps: " << settings.Get_show_fps() << std::endl;
  std::cout << "show_score: " << settings.Get_show_score() << std::endl;
  std::cout << "data_path: " << settings.Get_data_path() << std::endl;

  this->weight_file_edit->setText(QString::fromStdString(settings.Get_weight_file()));
  this->config_file_edit->setText(QString::fromStdString(settings.Get_config_file()));
  this->score_spinbox->setValue(settings.Get_t_score());
  this->show_fps_chk->setChecked(settings.Get_show_fps());
  this->show_score_chk->setChecked(settings.Get_show_score());
  this->data_file_edit->setText(QString::fromStdString(settings.Get_data_path()));
}

void FaceDetectView::select_image()
{
  std::cout << "button clicked ...." << std::endl;
  if (this->img_file_rbt->isChecked())
  {
    auto fileName = QFileDialog::getOpenFileName(this, "Open Image", QDir::homePath() + "/opencv_tutorial_data/images", tr("*.jpg *.png"));
    if (fileName.isEmpty())
    {
      return;
    }
    this->data_file_edit->setText(fileName);
    QPixmap pixmap(fileName);
    pixmap = pixmap.scaled(QSize(800, 500), Qt::KeepAspectRatio);
    this->image_label->setPixmap(pixmap);
  }
  if (this->video_file_rbt->isChecked())
  {
    auto fileName = QFileDialog::getOpenFileName(this, "Open Image", QDir::homePath() + "/opencv_tutorial_data/images", tr("*.mp4"));
    if (fileName.isEmpty())
    {
      return;
    }
    this->data_file_edit->setText(fileName);
  }
}

void FaceDetectView::select_weight_file()
{
  std::cout << "button clicked ...." << std::endl;
  auto fileName = QFileDialog::getOpenFileName(this, "选择模型权重文件", QDir::homePath() + "/opencv_tutorial_data/models/face_detector", tr("Weight(*.pb)"));
  if (fileName.isEmpty())
  {
    return;
  }
  this->weight_file_edit->setText(fileName);
}

void FaceDetectView::select_config_file()
{
  std::cout << "button clicked ...." << std::endl;
  auto fileName = QFileDialog::getOpenFileName(this, "选择模型配置文件", QDir::homePath() + "/opencv_tutorial_data/models/face_detector", tr("Config(*.pbtxt)"));
  if (fileName.isEmpty())
  {
    return;
  }
  this->config_file_edit->setText(fileName);
}

QPixmap imgTransfer(cv::Mat &frame)
{
  cv::Mat image;
  cv::cvtColor(frame, image, cv::COLOR_BGR2RGB);

  QImage img = QImage(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
  img = img.scaled(QSize(800, 500), Qt::KeepAspectRatio);
  QPixmap pixmap;

  return pixmap.fromImage(img);
}

void FaceDetectView::do_face_detect()
{
  auto weight_file = this->weight_file_edit->text();
  auto config_file = this->config_file_edit->text();
  float t_score = this->score_spinbox->value();
  bool show_fps = this->show_fps_chk->isChecked();
  bool show_score = this->show_score_chk->isChecked();
  auto data_file = this->data_file_edit->text();

  auto ret = QMessageBox::question(this, "选择", "你确定要运行人脸检测吗?", QMessageBox::StandardButtons(QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No));
  if (ret == QMessageBox::StandardButton::No)
  {
    return;
  }

  if (weight_file.isEmpty() || config_file.isEmpty() || data_file.isEmpty())
  {
    QMessageBox::warning(this, "警告", "模型或者数据未设置...");
    return;
  }

  InterfaceSettings settings;
  settings.Set_config_file(config_file.toStdString());
  settings.Set_weight_file(weight_file.toStdString());
  settings.Set_t_score(t_score);
  settings.Set_show_fps(show_fps);
  settings.Set_show_score(show_score);
  settings.Set_data_path(data_file.toStdString());
  settings.Dump_settings();

  this->face_detect_thread = new FaceDetectThread(settings); // 修改为指针

  qRegisterMetaType<cv::Mat>("cv::Mat");

  connect(this->face_detect_thread, SIGNAL(sendResult(cv::Mat)), this, SLOT(postProcess(cv::Mat)));
  connect(this->face_detect_thread, &FaceDetectThread::finished, this->face_detect_thread, &QObject::deleteLater);
  this->face_detect_thread->start();

  this->applyBtn->setEnabled(false);
}

void FaceDetectView::postProcess(cv::Mat frame)
{
  if (frame.empty())
  {
    this->applyBtn->setEnabled(true);
    return;
  }
  this->image_label->setPixmap(imgTransfer(frame));
}